home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / utils / error / elog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-06  |  6.1 KB  |  290 lines

  1. /*
  2.  * elog.c -- 
  3.  *    error logger
  4.  */
  5. #include <stdio.h>
  6. #include <strings.h>
  7. #include <sys/file.h>
  8. #include <sys/types.h>
  9. #include <varargs.h>
  10.  
  11. #include "tmp/postgres.h"
  12. #include "utils/log.h"
  13. #include "installinfo.h"
  14.  
  15. RcsId("$Header: /private/postgres/src/utils/error/RCS/elog.c,v 1.23 1992/08/07 00:43:22 mao Exp $");
  16.  
  17.  
  18. int    Debug_file = -1;
  19. int    Err_file = -1;
  20. int    ElogDebugIndentLevel;
  21.  
  22. /*
  23.  *  If the parser has detected an empty query from the front end, then
  24.  *  there is a chance that the front end has shut down.  If this happens,
  25.  *  and we try to send a bunch of elog messages over our connection to
  26.  *  the front end, and we're running Ultrix 3.x, then fflush on the
  27.  *  connection socket can cause us to die without a core dump.  Cool, yes?
  28.  *  The global below is set in PostgresMain and used here to work around
  29.  *  this operating system bug.
  30.  */
  31.  
  32. void
  33. EnableELog(enable)
  34. int enable;
  35. {
  36.     static int numEnabled;
  37.     static int fault; 
  38.  
  39.     Assert(fault == 0);
  40.  
  41.     if (!enable && --numEnabled)
  42.     return;
  43.     if (enable && numEnabled++)
  44.     return;
  45.  
  46.     ++fault;
  47.     if (enable) {
  48.     /* XXX */
  49.     ;
  50.     } else {
  51.     /* XXX */
  52.     ;
  53.     }
  54.     --fault;
  55. }
  56.  
  57.  
  58. /*VARARGS2*/
  59. void
  60. elog(va_alist)
  61. va_dcl
  62. {
  63.     va_list ap;
  64.     register int    lev;
  65.     char        *fmt;
  66.     char        buf[ELOG_MAXLEN], line[ELOG_MAXLEN];
  67.     register char    *bp, *cp;
  68.     extern    int    errno, sys_nerr;
  69.     extern    char    *sys_errlist[], *ctime(), *sprintf();
  70. #ifndef PG_STANDALONE
  71.     extern    FILE    *Pfout;
  72. #endif /* !PG_STANDALONE */
  73.     time_t        tim, time();
  74.     int        len;
  75.     int        i = 0;
  76.  
  77.     va_start(ap);
  78.     lev = va_arg(ap, int);
  79.     fmt = va_arg(ap, char *);
  80.     if (lev == DEBUG && Debug_file < 0) {
  81.         return;
  82.     }
  83.     switch (lev) {
  84.     case NOIND:
  85.         i = ElogDebugIndentLevel-1;
  86.         if (i < 0) i = 0;
  87.         if (i > 30) i = i%30;
  88.         cp = "DEBUG:";
  89.         break;
  90.     case DEBUG:
  91.         i = ElogDebugIndentLevel;
  92.         if (i < 0) i = 0;
  93.         if (i > 30) i = i%30;
  94.         cp = "DEBUG:";
  95.         break;
  96.     case NOTICE:
  97.         cp = "NOTICE:";
  98.         break;
  99.     case WARN:
  100.         cp = "WARN:";
  101.         break;
  102.     default:
  103.         sprintf(line, "FATAL %d:", lev);
  104.         cp = line;
  105.     }
  106.     time(&tim);
  107.     strcat(strcpy(buf, cp), ctime(&tim)+4);
  108.     bp = buf+strlen(buf)-6;
  109.     *bp++ = ':';
  110.     while (i-- >0) *bp++ = ' ';
  111.     for (cp = fmt; *cp; cp++)
  112.         if (*cp == '%' && *(cp+1) == 'm') {
  113.             if (errno < sys_nerr && errno >= 0)
  114.                 strcpy(bp, sys_errlist[errno]);
  115.             else
  116.                 sprintf(bp, "error %d", errno);
  117.             bp += strlen(bp);
  118.             cp++;
  119.         } else
  120.             *bp++ = *cp;
  121.     *bp = '\0';
  122.     vsprintf(line, buf, ap);
  123.     va_end(ap);
  124.     len = strlen(strcat(line, "\n"));
  125.     if (Debug_file > -1)
  126.         write(Debug_file, line, len);
  127.     if (lev == DEBUG || lev == NOIND)
  128.         return;
  129.  
  130.     /*
  131.      *  If there's an error log file other than our channel to the
  132.      *  front-end program, write to it first.  This is important
  133.      *  because there's a bug in the socket code on ultrix.  If the
  134.      *  front end has gone away (so the channel to it has been closed
  135.      *  at the other end), then writing here can cause this backend
  136.      *  to exit without warning -- that is, write() does an exit().
  137.      *  In this case, our only hope of finding out what's going on
  138.      *  is if Err_file was set to some disk log.  This is a major pain.
  139.      */
  140.  
  141.     if (Err_file > -1 && Debug_file != Err_file) {
  142.         if (write(Err_file, line, len) < 0) {
  143.             write(open("/dev/console", O_WRONLY, 0666), line, len);
  144.             fflush(stdout);
  145.             fflush(stderr);
  146.             exitpg(lev);
  147.         }
  148. #ifndef linux
  149.         /*
  150.          * Sorry, Linux does not seem to have fsync() (yet).
  151.          */
  152.         fsync(Err_file);
  153. #endif
  154.     }
  155.  
  156. #ifndef PG_STANDALONE
  157.     /* Send IPC message to the front-end program */
  158.     if (Pfout != NULL && lev > DEBUG) {
  159.         /* notices are not exactly errors, handle it differently */
  160.         if (lev == NOTICE) 
  161.             pq_putnchar("N", 1);
  162.         else
  163.             pq_putnchar("E", 1);
  164.         pq_putint(-101, 4);    /* should be query id */
  165.         pq_putstr(line);
  166.         pq_flush();
  167.     }
  168. #endif /* !PG_STANDALONE */
  169.  
  170.     if (lev == WARN) {
  171.         ProcReleaseSpins(NULL);    /* get rid of spinlocks we hold */
  172.         kill(getpid(), 1);    /* abort to traffic cop */
  173.     }
  174.  
  175.     if (lev == FATAL) {
  176.         /*
  177.          * Assume that if we have detected the failure we can
  178.          * exit with a normal exit status.  This will prevent
  179.          * the postmaster from cleaning up when it's not needed.
  180.          */
  181.         fflush(stdout);
  182.         fflush(stderr);
  183.         ProcReleaseSpins(NULL);    /* get rid of spinlocks we hold */
  184.         ProcReleaseLocks();    /* get rid of real locks we hold */
  185.         exitpg(0);
  186.     }
  187.  
  188.     if (lev > FATAL) {
  189.         fflush(stdout);
  190.         fflush(stderr);
  191.         exitpg(lev);
  192.     }
  193. }
  194.  
  195.  
  196. /*
  197.  *    GetDataHome
  198.  *
  199.  *    Extract the installation home directory from the environment.
  200.  */
  201.  
  202. extern char    *PostgresHomes[];
  203. extern int    NStriping;
  204. extern int    StripingMode;
  205.  
  206. char *
  207. GetDataHome()
  208. {
  209.     char        *home;
  210.     char        *p, *p1;
  211.     int        i;
  212.     extern char    *getenv();
  213.  
  214.     home = getenv("POSTGRESHOME");
  215.     if (!StringIsValid(home)) {
  216.         home = getenv("POSTHOME");
  217.     }
  218.     if (!StringIsValid(home)) {
  219.         home = DATAHOME;
  220.     }
  221.     if (!StringIsValid(home)) return NULL;
  222.     p = home;
  223.     i = 0;
  224.     while ((p1 = index(p, ':')) != NULL) {
  225.        *p1 = '\0';
  226.        PostgresHomes[i++] = p;
  227.        p = p1 + 1;
  228.      }
  229.     if (*p >= '0' && *p <= '9') {
  230.         /* specify raid level */
  231.         StripingMode = atoi(p);
  232.       }
  233.     else {
  234.         PostgresHomes[i++] = p;
  235.       }
  236.     NStriping = i;
  237.     if (StripingMode == 1) {
  238.         if (NStriping % 2 != 0)
  239.         elog(FATAL,"RAID Level 1 has to have an even number of disks.");
  240.         NStriping /= 2;
  241.       }
  242.     else if (StripingMode < 0 || StripingMode > 5)
  243.         elog(FATAL, "We only have RAID Level 0 -- 5.");
  244.     else if (StripingMode > 1 && StripingMode < 5)
  245.         elog(FATAL, "only RAID 0, 1 and 5 are supported.");
  246.     return(home);
  247. }
  248.  
  249.  
  250. ErrorFileOpen()
  251. {
  252.     int        fd;
  253.     char        buffer[MAXPGPATH];
  254.     extern char    *GetDataHome();
  255.  
  256.     fd = fileno(stderr);
  257.  
  258.     if (fcntl(fd, F_GETFD, 0) < 0) {
  259.         sprintf(buffer, "%s/data/pg.errors\0", GetDataHome());
  260.         fd = open(buffer, O_CREAT|O_APPEND|O_WRONLY, 0666);
  261.         if (fd < 0)
  262.             elog(FATAL, "ErrorFileOpen: open(%s) failed", buffer);
  263.     }
  264.  
  265.     return(fd);
  266. }
  267.  
  268.  
  269. DebugFileOpen()
  270. {
  271.     int        fd;
  272.     char        buffer[MAXPGPATH];
  273.     extern char    *GetDataHome();
  274.  
  275.     fd = fileno(stderr);
  276.     if (fcntl(fd, F_GETFD, 0) < 0) {
  277.         sprintf(buffer, "%s/data/pg.debug\0", GetDataHome());
  278. /*
  279.         elog(NOTICE, "DebugFileOpen: opening %s", buffer);
  280. */
  281.         fd = open(buffer, O_CREAT|O_APPEND|O_WRONLY, 0666);
  282.         if (fd < 0)
  283.             elog(FATAL, "DebugFileOpen: open(%s) failed", buffer);
  284.     }
  285. /*
  286.     elog(NOTICE, "DebugFileOpen: opened %s, fd=%d", buffer, fd);
  287. */
  288.     return(fd);
  289. }
  290.